t
List and Loop Annotations Together:         Mixed Multiplexes*750*

*209**525*List and Loop*589* annotations*539* can be applied to a single operation to create a*522* mixed multiplex*728*. You can gain insight into a mixed multiplex’s behavior by combining the railroad and cattle-chute metaphors. A mixed multiplex is like a train looping around on a siding track where there is a cattle chute. On each revolution around the siding, the train picks up a cow. Not a very efficient way to load cattle, but it is an analogy to the behavior of a mixed multiplex.

Apply a mixed*522* multiplex form to an addition, +, primitive to turn it into a summation operation for adding up a list of numbers.

u
Create a new universal method, Add Up, and edit its case window (comments optional) as shown below. You must apply the List annotation before applying the Loop annotation. 

You’ll notice that the Loop annotation automatically applies itself to both the selected terminal and the sole output root of the addition-primitive operation. In fact, you can make a mirror-image summation multiplex:

which performs the same computation as the first example. 

u
To see how the multiplex in Add Up is working, select Trace in the Exec menu and execute the method.

u
When the execution window appears, press Return four times. The multiplex performs its iterative computation in one fell swoop. Single click and hold the mouse button down on the loop root output of the + operation and you see that the sum of six has already been computed. 

You have no chance to step through the mixed multiplex when the operation so annotated is a primitive. Recall that*212* List and Loop annotations can be applied to method, local method, and primitive operations. To see this mixed multiplex at work, convert the primitive into a local method as follows:

u
Abort execution, select the + operation in Add Up, and choose Local in the Opers menu. The terminal and root annotation stay the same as the + primitive icon is transformed into a local method operation, named +. Open a case window on the + local method and edit the case to perform the basic addition that is done on each iteration of the multiplex.

u
With Trace mode still in effect, execute Add Up. Open the Stack window and press Return several times to step through the execution.

With the List and Loop annotations applied to a local-method operation rather than to a primitive, you have a chance to inspect the entry and exit values for each iteration of the mixed multiplex. By opening an execution window on Add Up, you can also confirm that a Loop annotated multiplex does not output any data value from its roots until iteration is complete.

u
When you finish stepping through the Add Up execution, turn Trace mode off before continuing in the tutorial.

t
Finish and Terminate Controls

*206**378*So far, to halt a multiplex you have relied on either exhausting a list of items to process or dropping to a next case. To provide increased iterative and list-processing flexibility, Prograph supports the control annotations*583* Finish and*1072* Terminate*593*. These annotations are familiar to those with experience in a text-based language such as Pascal, Basic, or C. If you do not have such experience, you can still find these control features easy to understand using Prograph’s visual execution features to see how they work.

*216*Terminate and Finish provide convenient ways to halt the execution of a loop or repeat multiplex such that a data value or object can be output by a multiplex. Once output has been produced, processing can continue in the case that contains the multiplex operation. Reflecting now on the examples you have executed so far in the tutorial, you see that the*757* Next Case annotation has precluded the possibility of using an iterative multiplex to calculate some value and output it in the case which contains the multiplex.

Terminate and Finish perform this important iterate- and-return-a-value function. The difference between them is based on how they stop executing iterations and what value they return. Closer inspection of the Terminate and Finish control*201* annotation icons gives an indication of how these control computations work.

The Terminate control has an iconic representation of an input bar along its top edge, while the Finish control shows an output bar along its bottom edge.

When a Terminate control is encountered, execution of the current case is stopped and the output values are those that were input to the terminated case—that is, the output values are the values of the last successful iteration. Create this example to see Terminate in action.

u
Create a universal method, find a C ?, containing two loop multiplex local methods, Terminate on C and Finish on C, to search a list for the letter C. As their names imply, one local contains a Terminate control when it finds a C, while the other has a Finish control. A counter tracks how many iterations each local performs.

u
Execute find a C ? and observe the dialogs that result.

The Terminate on C local produces a dialog that reads ("C" "s" "e")2, while Finish on C produces ("s" "e")3. The difference between terminating and finishing a looping multiplex has become quite apparent. 

Both locals meet their halt condition on the third iteration of the multiplex. For the execution in which the exit condition is met the Terminate control outputs the values that arrive on its input bar. The*377* Finish control continues processing the third iteration’s case, returning values reflecting the final detach-l and +1 operations.

__________________________________________________________
NOTE:  How do you decide whether to use a*536* Terminate or Finish annotation in a loop or repeating multiplex? 

Start by examining the multiplex in the calling method. If you are testing for some condition in the data being iteratively processed, and if no data values are being passed along datalinks attached to the roots of the multiplex, it often does not matter whether you use Terminate or Finish. It does matter if you are trying to iterate a specific number of times using an incremental or decremental counter. Terminating can come up one iteration short, while finishing can do one too many iterations, depending on the start and Match value you specify.

If the multiplex does pass output along datalinks attached to its roots, ask yourself what you expect those values to be, given some known input. You can then decide which halt control to use by setting up a test method that executes the multiplex with some known input values while Trace or Step/Show mode is on. In this way, you can quickly determine the behavior of the multiplex under each of the control annotations and under various start and Match values.
-----------------------------------------------------------

So far, you have explored rather tame control annotations. But just as IF/THEN/ELSE forms can be complexly nested one inside the other in text-based programming languages to achieve elaborate conditional behavior, so can you have multiple control annotations in a single Prograph case.

To see how control annotations can work together, create a more rigorous implementation of the find a C ? method.

u
Replicate the find a C ? method. In the new find a C ? #1 method, delete the Terminate on C local and its attached show operation. Also, replace the C in the input list with an A. Your new method should look like this:

u
Execute this method. You get an execution window on the Finish on C local. The automatic or manually displayed error message informs you that the*267* detach-l *838*operation has received an inappropriate input. Opening a Value window on this operation’s input reveals that you are trying to detach an item from an empty list.

It is clear that the method needs to trap the condition in which there are no C letters in the input list. In classic Western-movie fashion, you need to “head the empty list off at the pass.” Here, this means checking the input list for the empty condition before the detach-l operation is executed. In an arbitrary design decision, you decide that a simple No C found message along with a number indicating the length of the list processed is a sufficient response to this new condition. 

u
Abort execution, open the Finish on C local method and add a Match operation attached to the left input root. The test to perform is a Next Case on Success when an empty list is encountered.

u
Add a second case to Finish on C that returns the No C found message and passes the input iteration counter through, since this number equals the number of items processed in the now-exhausted list. Your edited method and local should look like this:

__________________________________________________________
NOTE:  Preview the execution order of the operations in the first case of the Finish on C local method. Click the input bar to select it, and then press Tab a number of times to inspect the order in which Prograph executes the operations of this local method. If the detach-l and Match on C operations are highlighted before the Match on an empty-list control, you need to connect a synchro from the Match on empty-list operation to the detach-l operation.

Prograph’s operations are data driven. They execute whenever all the required input data arrives. There may be times when you want to*686* control the order of execution in a method, as in the Finish on C local method. Using synchros to link specific operations guarantees a specific*357* order for method execution.
----------------------------------------------------------

Notice that the second case of the Finish on C local needs a Finish on Success control. Without this control, the multiplex keeps running and the sixth iteration breaks down with an error. The first case expects a list input on its left input, but it receives the No C found string from the previous execution of the multiplex’s second case.

The Finish control activates on success of the operation to which it is attached, which in this case is the output bar.

u
Execute the find a C ? #1 method. With the Finish control on a Match of an empty list, the multiplex halts with a dialog that reads No C found.5.

To get a clearer impression of how this multiple control, multicase method is working, turn on Trace mode and step through its execution. Edit the list to include a C character and notice how the behavior differs.

t
The Fail Control

An execution control that is likely to be new even for those with prior programming experience is Prograph’s Fail annotation. Fail lets you test a condition and decide immediately to halt execution of the case in which the Fail control is satisfied. Upon failing, the called method or local method notifies its calling operation that the called method or local has failed. How the calling operation reacts to the failure is a function of the control annotation on the calling operation icon. The example later in this section makes this clear.

But first, let’s put Prograph’s control annotations in perspective. Prograph’s Finish, Terminate, and Fail controls form a matrix along the dimensions that look at the control’s area of effect and whether the control continues or immediately stops execution of its case.

This chart distills information that appears in a comprehensive discussion covering Prograph controls in the Reference *938* manual. You may want to pause now or review these related sections of the Reference after you complete this tutorial. The Reference book gives you detailed information about Prograph’s rich control annotations.

You have already used the controls that affect cases. The Next Case controls respond immediately to a conditional test. The Next Case controls let you stop processing as soon as you determine that the current case does not apply to the current data conditions.

*193**204*In other circumstances, you want to test a condition and delay a response until the case has completed its execution. At the case level, the default control for deciding and continuing is*195* Continue on Success. Each operation that executes in a case, in effect, decides to keep going. This decision to keep going is a nondecision. When the operation executes and does not cause an error, data continues to flow along the datalinks. To keep from cluttering up a case diagram, this default control has no icon.

The complement of Continue on Success is Continue on Failure. *194**205*Continue on Failure is not used as often as the other controls. This control allows you to design a case that continues to execute even though a call to a method, or to a local method, from the case fails. 

For example, in the Barnyard Simulation of the previous chapter, you might create a Clean-up method that includes local methods to cleanup after birds, cleanup after cows, cleanup after cats, and so on. A Continue on Failure annotation on each of these local-method operations allows the Clean-up method to continue cleaning up even if execution of one of the locals determines that there are none of the particular class of animals it is designed to cleanup after. This local can then Fail to halt its own execution. A Continue on Failure annotation on this local allows the Clean-up method to continue even though a local within it has failed.

*366*At the method and local-method control level, the Fail annotation provides the ability to say, “If this condition occurs, nothing else within this method applies. Stop processing and report to the method that has called that there is nothing this method can do in this situation.” There is no circumstance in which failure is determined and then response delayed while the case completes execution. The lack of a delayed-failure control accounts for the blank cell in the*581**582* controls table above. 
To explore the Fail control, create the following methods, which work together to search a list for an item.

u
Create a two-case method, searcher, that feeds a list into a List annotated search list for item operation. Note the*214* Next Case*591* on Success control on the search list for item operation. Success here means that the operation successfully processes the entire list input. Since search list for item is implemented to Fail when the search item is found, successfully processing the list means that the item has not been found and is so indicated in the second case’s display dialog. If the search list for item operation does fail, the first case completes its execution by displaying an Item found. dialog.

u
Double-click the left side of the search list for item operation to create and open the case window of this new universal method. Edit its first case window, and then create and edit its second case to appear as follows:

The*365* Fail control can take two forms: 

Fail on Failure, 

, and Fail on Success, .

Both forms of Fail control are used in this example.

You might find it easier to understand Fail on Failure as “When this condition is FALSE, fail.” while*368* Fail on Success is “When this condition is TRUE, fail.”

Examine how search list for item is designed to fail. This method is designed to accept a list input and a search value. The list input is List annotated in searcher, its calling method. Success for a List annotated operation means successfully processing each item in its input list. 

The exit condition under which you want to stop iterating through the input list is when search list for item finds an item in the list that matches the search item. In other words, search list for item is to fail when it succeeds in finding the search item. This explains the Fail on Success test for equality between the item to be searched and the search item in the first case of search list for item.

But since a Prograph list may contain lists as elements, search list for item must be on the lookout for the situation in which an item to be searched is a list. In this situation, the search item can be within this list within the list. This explains the second conditional test in the first case of search list for item. The list? primitive’s Next Case on Success control drops to the second case of search list for item when the item to be searched is a list. 

Note that a synchro*1032* makes sure the equality test precedes the test of whether the item is a list. If no synchro is present, it is possible that the list? test could precede the equality test and the search might drop to the second case without catching the match.

The second case of search list for item makes a recursive call to search list for item with the list element from the original list as the input to be searched. Note that the recursive call to search list for item is annotated with a*367* Fail on Failure control. In the event that this call to search list for item fails by finding the search item in the list to be searched, this control passes the failure message upward to its calling method.

___________________________________________________________
NOTE:  While there are two varieties of Fail control—Fail on Failure and Fail on Success—it is important to understand that the propagated fail message is simply, “The method called failed.” The calling method does not know whether the called method failed due to success or failure.

So when you are deciding on the kind of control you should use to annotate a calling-operation icon, ask yourself, “What should this method do when this operation fails?” The conditions under which the called operation failed are its business. Your decision in the calling method is independent of the conditional test that generates the failure response.

Understanding the relationship between controls within methods and on operation icons that call those methods can do much to help you decide how to achieve the desired flow control within and between your methods.
----------------------------------------------------------

The recursive call in the second case of search list for item also consistently handles the deep nesting of lists within lists. In the case of many recursive calls to search list for item, when the item is found, the failure message is passed level to level until it reaches the top level and the search list for item call in searcher is completed by executing its Item found. message. 

All this rather abstract description can be confusing, so let Prograph show you how it processes failure.

u
Execute searcher as written. In a flash you see the Item found. dialog. To see searcher in action, open the Stack window and turn Trace mode on.

u
Execute searcher and step through its full execution. Notice that the recursive call to search list for item is completed without failing. The original call to search list for item does fail when the “d” character is found as the tail of the original list input. This failure message is passed back to the search list for item call within searcher, which then completes its execution. searcher does not drop to its second case since the original call to search list for item does not successfully complete processing of the input list, and therefore the Next Case on Success is not triggered.

u
Edit the original input list in searcher to be (a (b c (a b (c d) ) e) f). Open the Stack window and again execute searcher and step through its execution.

This time you recurse four deep in calls to search list for item. This execution fails when the “d” character in the innermost list is tested:

u
Press Return after the “d” character is found and watch how quickly and directly the failure message propagates up the stack of recursive calls to search list for item. All calls to search list for item are peeled from the stack and searcher is notified that the original call to search list for item has failed. A few more presses of Return, and you see the Item found. dialog. After a couple of more steps the execution is complete.

You have now explored a wide variety of basic features that give Prograph methods the power to do just about anything you can imagine. Multiple cases, multiple control annotations, multiplexes, and local methods all work together and give you the flexibility to implement your most complex computation designs.

With this increased understanding of the structure and function of Prograph methods, take a few minutes to open and inspect some of the files in the Tutorial Examples, Learning Prograph, and other example folders. Be on the lookout for elaborate control annotations, multicase locals, and multiplexes. When you find something interesting, set a Breakpoint or turn on Step/Show and execute the example. Use the Stack window to get a deeper understanding of how these features work together. 

The time you spend inspecting and running Prograph examples will be repaid many times as you delve into the Application Builder tutorial and as you begin your own Prograph application development.

t
Check Your Progress

*159*Review the list below. Be sure you are familiar with the concepts presented in this chapter before continuing in the tutorials.

In this tutorial, you have learned how to:

4 specify methods with special annotations for conditional execution

4 use the case window’s Case List pane to re-sort the order of cases for a method and to insert new cases

4 use local methods to control datalink complexity in methods

4 specify conditional subtasks through the use of locals with cases

4 use List and Loop annotations alone or in combination to achieve a high level of complexity in the methods of an application

4 distinguish between the Terminate and Finish control-annotation icons

4 control the flow of data in a method by using Finish and Terminate control annotations

4 use control annotations for cases, loop, and repeat iterations and methods.

You have also learned how helpful it is to use the many debugging facilities Prograph provides as you develop multiple control, multicase methods. Take some time to practice using these facilities as you review the activities covered in this tutorial. The more comfortable you become with the basics of Prograph’s case structure, control annotations, and multiplexes, the more quickly you can begin to develop your own complex applications. When you are ready to dig into Application Builder, continue on to the next tutorial.